package scu.maqiang.electromagnetics;

import scu.maqiang.fes.FES2T31;
import scu.maqiang.mesh.Mesh2T3;
import scu.maqiang.mesh.ScalarFunc;
import scu.maqiang.numeric.CG;

public class EdgeElement2D {
    public static void main(String[] args) {
        double[] x = {0.0, 1.0, 0.5};
        double[] y = {0.0, 0.0, 0.5 * Math.sqrt(3)};
        Mesh2T3 mesh = new Mesh2T3().triangle(x, y, 20);
//        mesh.toTecplot("TriangleMesh.dat");
        double[][] gradient = new double[3][2];

        double area = CG.gradient2DT3(x, y, gradient);
        double a1 = gradient[0][0];
        double b1 = gradient[0][1];
        double c1 = (x[1] * y[2] - x[2] * y[1]) / (2 * area);
        FES2T31 fs = new FES2T31(mesh);
        ScalarFunc basisFunc1 = (xy, label, param) -> a1 * xy[0] + b1 * xy[1] + c1;
        double[] basis1 = fs.valueFromFunc(basisFunc1, null);

        double a2 = gradient[1][0];
        double b2 = gradient[1][1];
        double c2 = (x[2] * y[0] - x[0] * y[2]) / (2 * area);
        ScalarFunc basisFunc2 = (xy, label, param) -> a2 * xy[0] + b2 * xy[1] + c2;
        double[] basis2 = fs.valueFromFunc(basisFunc2, null);

        double a3 = gradient[2][0];
        double b3 = gradient[2][1];
        double c3 = (x[0] * y[1] - x[1] * y[0]) / (2 * area);
        ScalarFunc basisFunc3 = (xy, label, param) -> a3 * xy[0] + b3 * xy[1] + c3;
        double[] basis3 = fs.valueFromFunc(basisFunc3, null);
        double[][] basises = {basis1, basis2, basis3};
        mesh.toTecplot("basisFuncs.dat", basises);

        double len1 = Math.sqrt((x[0] - x[1]) * (x[0] - x[1]) + (y[0] - y[1]) * (y[0] - y[1]));
        ScalarFunc edgeFunc1X = (xy, label, param) -> len1 * (basisFunc1.action(xy, label, param) * gradient[1][0]
                                                             -basisFunc2.action(xy, label, param) * gradient[0][0] );
        ScalarFunc edgeFunc1Y = (xy, label, param) -> len1 * (basisFunc1.action(xy, label, param) * gradient[1][1]
                -basisFunc2.action(xy, label, param) * gradient[0][1] );
        double[] edge1X = fs.valueFromFunc(edgeFunc1X, null);
        double[] edge1Y = fs.valueFromFunc(edgeFunc1Y, null);
        double[][] edgeBasis1 = {edge1X, edge1Y};
        mesh.toTecplot("edgeBasises.dat", edgeBasis1);

        double len2 = Math.sqrt((x[1] - x[2]) * (x[1] - x[2]) + (y[1] - y[2]) * (y[1] - y[2]));
        ScalarFunc edgeFunc2X = (xy, label, param) -> len2 * (basisFunc2.action(xy, label, param) * gradient[2][0]
                -basisFunc3.action(xy, label, param) * gradient[1][0] );
        ScalarFunc edgeFunc2Y = (xy, label, param) -> len2 * (basisFunc2.action(xy, label, param) * gradient[2][1]
                -basisFunc3.action(xy, label, param) * gradient[1][1] );
        double[] edge2X = fs.valueFromFunc(edgeFunc2X, null);
        double[] edge2Y = fs.valueFromFunc(edgeFunc2Y, null);
        double[][] edgeBasis2 = {edge2X, edge2Y};
        mesh.toTecplot("edgeBasises2.dat", edgeBasis2);

        double len3 = Math.sqrt((x[2] - x[0]) * (x[2] - x[0]) + (y[2] - y[0]) * (y[2] - y[0]));
        ScalarFunc edgeFunc3X = (xy, label, param) -> len3 * (basisFunc3.action(xy, label, param) * gradient[0][0]
                -basisFunc1.action(xy, label, param) * gradient[2][0] );
        ScalarFunc edgeFunc3Y = (xy, label, param) -> len3 * (basisFunc3.action(xy, label, param) * gradient[0][1]
                -basisFunc1.action(xy, label, param) * gradient[2][1] );
        double[] edge3X = fs.valueFromFunc(edgeFunc3X, null);
        double[] edge3Y = fs.valueFromFunc(edgeFunc3Y, null);
        double[][] edgeBasis3 = {edge3X, edge3Y};
        mesh.toTecplot("edgeBasises3.dat", edgeBasis3);

        double[] u = {1.0, 2.0, 3.0};
        ScalarFunc uxFunc = (xy, label, param) -> u[0] * edgeFunc1X.action(xy, label, param) + u[1] * edgeFunc2X.action(xy, label, param) + u[2] * edgeFunc3X.action(xy, label, param);
        ScalarFunc uyFunc = (xy, label, param) -> u[0] * edgeFunc1Y.action(xy, label, param) + u[1] * edgeFunc2Y.action(xy, label, param) + u[2] * edgeFunc3Y.action(xy, label, param);
        double[] uX = fs.valueFromFunc(uxFunc, null);
        double[] uY = fs.valueFromFunc(uyFunc, null);
        double[][] uXY = {uX, uY};
        mesh.toTecplot("funcUXY.dat", uXY);
    }
}
